home *** CD-ROM | disk | FTP | other *** search
/ Windows Game Programming for Dummies (2nd Edition) / WinGamProgFD.iso / pc / DirectX SDK / DXSDK / samples / Multimedia / DirectInput / DIConfig / useful.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-10-08  |  13.0 KB  |  627 lines

  1. //-----------------------------------------------------------------------------
  2. // File: useful.cpp
  3. //
  4. // Desc: Contains various utility classes and functions to help the
  5. //       UI carry its operations more easily.
  6. //
  7. // Copyright (C) 1999-2001 Microsoft Corporation. All Rights Reserved.
  8. //-----------------------------------------------------------------------------
  9.  
  10. #include <windows.h>
  11. #include <tchar.h>
  12. #include <wchar.h>
  13. #include <stdio.h>
  14. #include <stdarg.h>
  15.  
  16. // assert include (make sure assert actually works with build)
  17. #ifdef DBG
  18. #undef NDEBUG
  19. #endif
  20. #include <assert.h>
  21.  
  22. #include "useful.h"
  23. #include "collections.h"
  24.  
  25.  
  26. /*--------- \/ stuff for collections.h \/ ---------*/
  27. BOOL AfxIsValidAddress( const void* lp, UINT nBytes, BOOL bReadWrite)
  28. {
  29. //    return lp != NULL;
  30.  
  31.     // simple version using Win-32 APIs for pointer validation.
  32.     return (lp != NULL && !IsBadReadPtr(lp, nBytes) &&
  33.         (!bReadWrite || !IsBadWritePtr((LPVOID)lp, nBytes)));
  34. }
  35.  
  36. CPlex* PASCAL CPlex::Create(CPlex*& pHead, UINT nMax, UINT cbElement)
  37. {
  38.     assert(nMax > 0 && cbElement > 0);
  39.     CPlex* p = (CPlex*) new BYTE[sizeof(CPlex) + nMax * cbElement];
  40.             // may throw exception
  41.     if (p)
  42.     {
  43.         p->pNext = pHead;
  44.         pHead = p;  // change head (adds in reverse order for simplicity)
  45.     }
  46.     return p;
  47. }
  48.  
  49. void CPlex::FreeDataChain()     // free this one and links
  50. {
  51.     CPlex* p = this;
  52.     while (p != NULL)
  53.     {
  54.         BYTE* bytes = (BYTE*) p;
  55.         CPlex* pNext = p->pNext;
  56.         delete[] bytes;
  57.         p = pNext;
  58.     }
  59. }
  60. /*--------- /\ stuff for collections.h /\ ---------*/
  61.  
  62.  
  63. int ConvertVal(int x, int a1, int a2, int b1, int b2)
  64. {
  65.     assert(a1 != a2 && a2 - a1);
  66.     return MulDiv(x - a1, b2 - b1, a2 - a1) + b1;
  67. }
  68.  
  69. double dConvertVal(double x, double a1, double a2, double b1, double b2)
  70. {
  71.     assert(a1 != a2 && a2 - a1);
  72.     return (x - a1) * (b2 - b1) / (a2 - a1) + b1;
  73. }
  74.  
  75. SIZE GetRectSize(const RECT &rect)
  76. {
  77.     SIZE size = {
  78.         rect.right - rect.left,
  79.         rect.bottom - rect.top};
  80.     return size;
  81. }
  82.  
  83. SIZE GetTextSize(LPCTSTR tszText, HFONT hFont)
  84. {
  85.     if (!tszText)
  86.     {
  87.         SIZE z = {0, 0};
  88.         return z;
  89.     }
  90.     RECT trect = {0, 0, 1, 1};
  91.     HDC hDC = CreateCompatibleDC(NULL);
  92.     if (hDC != NULL)
  93.     {
  94.         HGDIOBJ hOld = NULL;
  95.         if (hFont)
  96.             hOld = SelectObject(hDC, hFont);
  97.         DrawText(hDC, tszText, -1, &trect, DT_CALCRECT | DT_NOPREFIX);
  98.         if (hFont)
  99.             SelectObject(hDC, hOld);
  100.         DeleteDC(hDC);
  101.     }
  102.     SIZE size = {trect.right - trect.left, trect.bottom - trect.top};
  103.     return size;
  104. }
  105.  
  106. int GetTextHeight(HFONT hFont)
  107. {
  108.     static const TCHAR str[] = _T("Happy Test!  :D");
  109.     SIZE size = GetTextSize(str, hFont);
  110.     return size.cy;
  111. }
  112.  
  113. int vFormattedMsgBox(HINSTANCE hInstance, HWND hParent, UINT uType, UINT uTitle, UINT uMsg, va_list args)
  114. {
  115.     int i;
  116.     const int len = 1024;
  117.     static TCHAR title[len], format[len], msg[len];
  118.  
  119.     if (!LoadString(hInstance, uTitle, title, len))
  120.         _tcscpy(title, _T("(could not load title string)"));
  121.     
  122.     if (!LoadString(hInstance, uMsg, format, len))
  123.         return MessageBox(hParent, _T("(could not load message/format string)"), title, uType);
  124.  
  125. #ifdef WIN95
  126.     {
  127.         char *psz = NULL;
  128.         char szDfs[1024]={0};
  129.         strcpy(szDfs,format);                            // make a local copy of format string
  130.         while (psz = strstr(szDfs,"%p"))                // find each %p
  131.             *(psz+1) = 'x';                                // replace each %p with %x
  132.         i = _vsntprintf(msg, len, szDfs, args);            // use the local format string
  133.     }
  134. #else
  135.     {
  136.         i = _vsntprintf(msg, len, format, args);
  137.     }
  138. #endif
  139.  
  140.     if (i < 0)
  141.         return MessageBox(hParent, _T("(could not format message)"), title, uType);
  142.  
  143.     if (i < 1)
  144.         msg[0] = 0;
  145.  
  146.     return MessageBox(hParent, msg, title, uType);
  147. }
  148.  
  149. int FormattedMsgBox(HINSTANCE hInstance, HWND hParent, UINT uType, UINT uTitle, UINT uMsg, ...)
  150. {
  151.     va_list args;
  152.     va_start(args, uMsg);
  153.     int i = vFormattedMsgBox(hInstance, hParent, uType, uTitle, uMsg, args);
  154.     va_end(args);
  155.     return i;
  156. }
  157.  
  158. BOOL UserConfirm(HINSTANCE hInstance, HWND hParent, UINT uTitle, UINT uMsg, ...)
  159. {
  160.     va_list args;
  161.     va_start(args, uMsg);
  162.     int i = vFormattedMsgBox(hInstance, hParent, MB_ICONQUESTION | MB_YESNO, uTitle, uMsg, args);
  163.     va_end(args);
  164.     return i == IDYES;
  165. }
  166.  
  167. int FormattedErrorBox(HINSTANCE hInstance, HWND hParent, UINT uTitle, UINT uMsg, ...)
  168. {
  169.     va_list args;
  170.     va_start(args, uMsg);
  171.     int i = vFormattedMsgBox(hInstance, hParent, MB_OK | MB_ICONSTOP, uTitle, uMsg, args);
  172.     va_end(args);
  173.     return i;
  174. }
  175.  
  176. int FormattedLastErrorBox(HINSTANCE hInstance, HWND hParent, UINT uTitle, UINT uMsg, DWORD dwError)
  177. {
  178.     // format an error message from GetLastError().
  179.     LPVOID lpMsgBuf = NULL;
  180.     DWORD result = FormatMessage(
  181.         FORMAT_MESSAGE_ALLOCATE_BUFFER |
  182.         FORMAT_MESSAGE_FROM_SYSTEM |
  183.         FORMAT_MESSAGE_IGNORE_INSERTS,
  184.         NULL,
  185.         dwError,
  186.         MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  187.         (LPTSTR) &lpMsgBuf,
  188.         0,
  189.         NULL);
  190.  
  191.     if (!result || lpMsgBuf == NULL)
  192.         return FormattedErrorBox(hInstance, hParent, uTitle, uMsg, 
  193.             _T("An unknown error occured (could not format the error code)."));
  194.  
  195.     int i = FormattedErrorBox(hInstance, hParent, uTitle, uMsg, (LPCTSTR)lpMsgBuf);
  196.  
  197.     LocalFree(lpMsgBuf);
  198.  
  199.     return i;
  200. }
  201.  
  202. LPTSTR AllocLPTSTR(LPCWSTR wstr)
  203. {
  204.     if (wstr == NULL)
  205.         return NULL;
  206.  
  207. #ifdef UNICODE
  208.     return _tcsdup(wstr);
  209. #else
  210.     int len = wcslen(wstr) * 2 + 1;
  211.     char *ret = (char *)malloc(len);
  212.     if (!ret)
  213.         return NULL;
  214.     WideCharToMultiByte(CP_ACP, 0, wstr, -1, ret, len, NULL, NULL);
  215.     ret[len-1] = '\0';
  216.     return ret;
  217. #endif
  218. }
  219.  
  220. LPTSTR AllocLPTSTR(LPCSTR str)
  221. {
  222.     if (str == NULL)
  223.         return NULL;
  224.  
  225. #ifndef UNICODE
  226.     return _tcsdup(str);
  227. #else
  228.     int len = strlen(str);
  229.     WCHAR *ret = (WCHAR *)malloc((len + 1) * sizeof(WCHAR));
  230.     if (!ret)
  231.         return NULL;
  232.     mbstowcs(ret, str, len);
  233.     ret[len] = L'\0';
  234.     return ret;
  235. #endif
  236. }
  237.  
  238. void CopyStr(LPWSTR dest, LPCWSTR src, size_t max)
  239. {
  240.     if (dest == NULL || src == NULL)
  241.         return;
  242.  
  243.     wcsncpy(dest, src, max);
  244. }
  245.  
  246. void CopyStr(LPSTR dest, LPCSTR src, size_t max)
  247. {
  248.     if (dest == NULL || src == NULL)
  249.         return;
  250.  
  251.     strncpy(dest, src, max);
  252. }
  253.  
  254. void CopyStr(LPWSTR dest, LPCSTR src, size_t max)
  255. {
  256.     if (dest == NULL || src == NULL)
  257.         return;
  258.  
  259.     mbstowcs(dest, src, max);
  260. }
  261.  
  262. void CopyStr(LPSTR dest, LPCWSTR src, size_t max)
  263. {
  264.     if (dest == NULL || src == NULL)
  265.         return;
  266.  
  267.     WideCharToMultiByte(CP_ACP, 0, src, -1, dest, max, NULL, NULL);
  268. }
  269.  
  270. LPWSTR AllocLPWSTR(LPCWSTR wstr)
  271. {
  272.     if (wstr == NULL)
  273.         return NULL;
  274.  
  275.     return _wcsdup(wstr);
  276. }
  277.  
  278. LPWSTR AllocLPWSTR(LPCSTR str)
  279. {
  280.     if (str == NULL)
  281.         return NULL;
  282.  
  283.     size_t len = strlen(str);
  284.     size_t retsize = mbstowcs(NULL, str, len);
  285.     WCHAR *ret = (WCHAR *)malloc((retsize + 1) * sizeof(WCHAR));
  286.     if (!ret)
  287.         return NULL;
  288.     mbstowcs(ret, str, len);
  289.     ret[retsize] = L'\0';
  290.     return ret;
  291. }
  292.  
  293. LPSTR AllocLPSTR(LPCWSTR wstr)
  294. {
  295.     if (wstr == NULL)
  296.         return NULL;
  297.  
  298.     size_t len = wcslen(wstr);
  299.     size_t retsize = WideCharToMultiByte(CP_ACP, 0, wstr, -1, NULL, 0, NULL, NULL);
  300.     CHAR *ret = (CHAR *)malloc((retsize + 1) * sizeof(CHAR));
  301.     if (!ret)
  302.         return NULL;
  303.     WideCharToMultiByte(CP_ACP, 0, wstr, -1, ret, retsize, NULL, NULL);
  304.     ret[retsize] = '\0';
  305.     return ret;
  306. }
  307.  
  308. LPSTR AllocLPSTR(LPCSTR str)
  309. {
  310.     if (str == NULL)
  311.         return NULL;
  312.  
  313.     return _strdup(str);
  314. }
  315.  
  316. LPTSTR AllocFileNameNoPath(LPTSTR path)
  317. {
  318.     TCHAR fname[_MAX_FNAME];
  319.     TCHAR ext[_MAX_EXT];
  320.  
  321.     if (path == NULL) return NULL;
  322.  
  323.     _tsplitpath(path, NULL, NULL, fname, ext);
  324.  
  325.     LPTSTR ret = (LPTSTR)malloc(sizeof(TCHAR) * (_tcslen(fname) + _tcslen(ext) + 1));
  326.     if (ret != NULL)
  327.     {
  328.         _tcscpy(ret, fname);
  329.         _tcscat(ret, ext);
  330.     }
  331.  
  332.     return ret;
  333. }
  334.  
  335. LPTSTR utilstr::Eject()
  336. {
  337.     LPTSTR str = m_str;
  338.     m_str = NULL;
  339.     m_len = 0;
  340.     return str;
  341. }
  342.  
  343. void utilstr::Empty()
  344. {
  345.     if (m_str != NULL)
  346.         free(m_str);
  347.     m_len = 0;
  348. }
  349.  
  350. bool utilstr::IsEmpty() const
  351. {
  352.     return !GetLength();
  353. }
  354.  
  355. int utilstr::GetLength() const
  356. {
  357.     if (m_str == NULL)
  358.         return 0;
  359.     if (!m_len)
  360.         return 0;
  361.  
  362.     return _tcslen(m_str);
  363. }
  364.  
  365. void utilstr::Format(LPCTSTR format, ...)
  366. {
  367.     static TCHAR buf[2048];
  368.     va_list args;
  369.     va_start(args, format);
  370. #ifdef WIN95
  371.     {
  372.         char *psz = NULL;
  373.         char szDfs[1024]={0};
  374.         strcpy(szDfs,format);  // make a local copy of format string
  375.         while (psz = strstr(szDfs,"%p"))  // find each %p
  376.             *(psz+1) = 'x';  // replace each %p with %x
  377.         _vsntprintf(buf, sizeof(buf)/sizeof(TCHAR), szDfs, args);  // use the local format string
  378.     }
  379. #else
  380.     {
  381.         _vsntprintf(buf, sizeof(buf)/sizeof(TCHAR), format, args);
  382.     }
  383. #endif
  384.     va_end(args);
  385.     equal(buf);
  386. }
  387.  
  388. void utilstr::equal(LPCTSTR str)
  389. {
  390.     Empty();
  391.     if (str == NULL)
  392.         return;
  393.     m_len = _tcslen(str);
  394.     m_str = (LPTSTR)malloc(sizeof(TCHAR) * (m_len + 1));
  395.     if (m_str != NULL)
  396.         _tcscpy(m_str, str);
  397.     else
  398.         m_len = 0;
  399. }
  400.  
  401. void utilstr::add(LPCTSTR str)
  402. {
  403.     if (str == NULL)
  404.         return;
  405.     if (IsEmpty())
  406.     {
  407.         equal(str);
  408.         return;
  409.     }
  410.     int len = _tcslen(str);
  411.     int newlen = m_len + len;
  412.     LPTSTR newstr = (LPTSTR)malloc(sizeof(TCHAR) * (newlen + 1));
  413.     if (newstr == NULL)
  414.         return;
  415.     _tcscpy(newstr, m_str);
  416.     _tcscat(newstr, str);
  417.     Empty();
  418.     m_str = newstr;
  419.     m_len = newlen;
  420. }
  421.  
  422. LPTSTR AllocFlagStr(DWORD value, const AFS_FLAG flag[], int flags)
  423. {
  424.     utilstr ret;    // return string
  425.     DWORD allknownbits = 0;  // check value to see if there are any bits
  426.                              // set for which we don't have a define
  427.  
  428.     // handle each flag
  429.     bool bflagfound = false;
  430.     for (int i = 0; i < flags; i++)
  431.     {
  432.         // set bit for this flag in allknownbits
  433.         allknownbits |= flag[i].value;
  434.  
  435.         // if this bit is set in the passed value, or the value
  436.         // is zero and we're on the zero flag,
  437.         // add the define for this bit/flag to the return string
  438.         if (value ? value & flag[i].value : !flag[i].value)
  439.         {
  440.             // adding binary or operators between flags
  441.             if (bflagfound)
  442.                 ret += _T(" | ");
  443.             ret += flag[i].name;
  444.             bflagfound = true;
  445.         }
  446.     }
  447.  
  448.     // now see if there are any unknown bits in passed flag
  449.     DWORD unknownbits = value & ~allknownbits;
  450.     if (unknownbits)
  451.     {
  452.         // add hex number for unknown bits
  453.         utilstr unk;
  454.         unk.Format(_T("0x%08X"), unknownbits);
  455.         if (bflagfound)
  456.             ret += _T(" | ");
  457.         ret += unk;
  458.     }
  459.  
  460.     // if value is zero (and no flags for zero) we should just set the string to "0"
  461.     if (!value && !bflagfound)
  462.         ret = _T("0");
  463.  
  464.     // now the string should definitely not be empty, in any case
  465.     assert(!ret.IsEmpty());
  466.  
  467.     // finally, add a comment that has hex number for entire value
  468.     // (for debugging)
  469.     utilstr temp;
  470.     temp.Format(_T(" /* 0x%08X */"), value);
  471.     ret += temp;
  472.  
  473.     // done
  474.     return ret.Eject();
  475. }
  476.  
  477. void PutLinePoint(HDC hDC, POINT p)
  478. {
  479.     MoveToEx(hDC, p.x, p.y, NULL);
  480.     LineTo(hDC, p.x + 1, p.y);
  481. }
  482.  
  483. void PolyLineArrowShadow(HDC hDC, POINT *p, int i)
  484. {
  485.     PolyLineArrow(hDC, p, i, TRUE);
  486. }
  487.  
  488. void PolyLineArrow(HDC hDC, POINT *rgpt, int nPoints, BOOL bDoShadow)
  489. {
  490.     int i;
  491.  
  492.     if (rgpt == NULL || nPoints < 1)
  493.         return;
  494.  
  495.     if (nPoints > 1)
  496.         for (i = 0; i < nPoints - 1; i++)
  497.         {
  498.             SPOINT a = rgpt[i], b = rgpt[i + 1];
  499.  
  500.             if (bDoShadow)
  501.             {
  502.                 int rise = abs(b.y - a.y), run = abs(b.x - a.x);
  503.                 bool vert = rise > run;
  504.                 int ord = vert ? 1 : 0;
  505.                 int nord = vert ? 0 : 1;
  506.                 
  507.                 for (int o = -1; o <= 1; o += 2)
  508.                 {
  509.                     SPOINT c(a), d(b);
  510.                     c.a[nord] += o;
  511.                     d.a[nord] += o;
  512.                     MoveToEx(hDC, c.x, c.y, NULL);
  513.                     LineTo(hDC, d.x, d.y);
  514.                 }
  515.  
  516.                 bool reverse = a.a[ord] > b.a[ord];
  517.                 SPOINT e(reverse ? b : a), f(reverse ? a : b);
  518.                 e.a[ord] -= 1;
  519.                 f.a[ord] += 1;
  520.                 PutLinePoint(hDC, e);
  521.                 PutLinePoint(hDC, f);
  522.             }
  523.             else
  524.             {
  525.                 MoveToEx(hDC, a.x, a.y, NULL);
  526.                 LineTo(hDC, b.x, b.y);
  527.             }
  528.         }
  529.  
  530.     POINT z = rgpt[nPoints - 1];
  531.  
  532.     if (bDoShadow)
  533.     {
  534.         POINT pt[5] = {
  535.             {z.x, z.y + 2},
  536.             {z.x + 2, z.y},
  537.             {z.x, z.y - 2},
  538.             {z.x - 2, z.y}, };
  539.         pt[4] = pt[0];
  540.         Polyline(hDC, pt, 5);
  541.     }
  542.     else
  543.     {
  544.         MoveToEx(hDC, z.x - 1, z.y, NULL);
  545.         LineTo(hDC, z.x + 2, z.y);
  546.         MoveToEx(hDC, z.x, z.y - 1, NULL);
  547.         LineTo(hDC, z.x, z.y + 2);
  548.     }
  549. }
  550.  
  551. BOOL bEq(BOOL a, BOOL b)
  552. {
  553.     bool c = !a, d = !b;
  554.     return (c == d) ? TRUE : FALSE;
  555. }
  556.  
  557. void DrawArrow(HDC hDC, const RECT &rect, BOOL bVert, BOOL bUpLeft)
  558. {
  559.     SRECT srect = rect;
  560.     srect.right--;
  561.     srect.bottom--;
  562.     int ord = bVert ? 1 : 0;
  563.     int nord = bVert ? 0 : 1;
  564.     SPOINT p(!bUpLeft ? srect.lr : srect.ul), b(!bUpLeft ? srect.ul : srect.lr);
  565.     b.a[ord] += bUpLeft ? -1 : 1;
  566.     SPOINT t = p;
  567.     t.a[nord] = (p.a[nord] + b.a[nord]) / 2;
  568.     SPOINT u;
  569.     u.a[ord] = b.a[ord];
  570.     u.a[nord] = p.a[nord];
  571.     POINT poly[] = { {t.x, t.y}, {u.x, u.y}, {b.x, b.y} };
  572.     Polygon(hDC, poly, 3);
  573. }
  574.  
  575. BOOL ScreenToClient(HWND hWnd, LPRECT rect)
  576. {
  577.     if (rect == NULL)
  578.         return FALSE;
  579.  
  580.     SRECT sr = *rect;
  581.  
  582.     if (ScreenToClient(hWnd, &sr.ul.p) &&
  583.         ScreenToClient(hWnd, &sr.lr.p))
  584.     {
  585.         *rect = sr;
  586.         return TRUE;
  587.     }
  588.  
  589.     return FALSE;
  590. }
  591.  
  592. BOOL ClientToScreen(HWND hWnd, LPRECT rect)
  593. {
  594.     if (rect == NULL)
  595.         return FALSE;
  596.  
  597.     SRECT sr = *rect;
  598.  
  599.     if (ClientToScreen(hWnd, &sr.ul.p) &&
  600.         ClientToScreen(hWnd, &sr.lr.p))
  601.     {
  602.         *rect = sr;
  603.         return TRUE;
  604.     }
  605.  
  606.     return FALSE;
  607. }
  608.  
  609. #define z ((L"\0")[0])
  610.  
  611. int StrLen(LPCWSTR s)
  612. {
  613.     if (s == NULL)
  614.         return 0;
  615.  
  616.     return wcslen(s);
  617. }
  618.  
  619. int StrLen(LPCSTR s)
  620. {
  621.     if (s == NULL)
  622.         return 0;
  623.  
  624.     return strlen(s);
  625. }
  626.  
  627.